package com.unitd.scheduler.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

/**
 * @desc Job任务配置类, 用于定义和处理Job配置信息
 * @filename JobConfig.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/14
 */
public class JobConfig implements Serializable {

	/** Job所在组名 */
	private String groupName;
	/** Job名称 */
	private String jobName;
	/** 定时器的执行时间表达式, 按照schedule的规则来定义(比如: 0/30 * * * * ?) */
	private String cronExpr;
	/** 调度器名称 */
	private String schedulerName;
	/** 是否运行中 */
	private boolean running = false;
	/** 是否启用 */
	private boolean active = true;
	@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
	/** 上一次运行开始时间 */
	private Date lastFireTime;
	@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
	/** 下一次运行开始时间 */
	private Date nextFireTime;
	/** 当前执行节点id */
	private String currentNodeId;
	/** 修改时间 */
	private long modifyTime;
	/** 错误信息 */
	private String errorMsg;
	/** 允许的最大偏差时间 */
	private static long allowDeviation = 1000 * 60 * 10;

	public JobConfig() {
	}

	/**
	 * @param groupName Job所在组名
	 * @param jobName   Job名称
	 * @param cronExpr  定时器的执行时间表达式,
	 * @desc 构造方法, 用于新建一个定时器任务配置对象
	 */
	public JobConfig(String groupName, String jobName, String cronExpr) {
		super();
		this.groupName = groupName;
		this.jobName = jobName;
		this.cronExpr = cronExpr;
		this.modifyTime = System.currentTimeMillis();
	}

	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public String getJobName() {
		return jobName;
	}

	public void seJobName(String jobName) {
		this.jobName = jobName;
	}

	public String getCronExpr() {
		return cronExpr;
	}

	public void setCronExpr(String cronExpr) {
		this.cronExpr = cronExpr;
	}

	public String getSchedulerName() {
		return schedulerName;
	}

	public void setSchedulerName(String schedulerName) {
		this.schedulerName = schedulerName;
	}

	public boolean isRunning() {
		return running;
	}

	public void setRunning(boolean running) {
		this.running = running;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	public Date getLastFireTime() {
		return lastFireTime;
	}

	public void setLastFireTime(Date lastFireTime) {
		this.lastFireTime = lastFireTime;
	}

	public Date getNextFireTime() {
		return nextFireTime;
	}

	public void setNextFireTime(Date nextFireTime) {
		this.nextFireTime = nextFireTime;
	}

	public String getCurrentNodeId() {
		return currentNodeId;
	}

	public void setCurrentNodeId(String currentNodeId) {
		this.currentNodeId = currentNodeId;
	}

	public long getModifyTime() {
		return modifyTime;
	}

	public void setModifyTime(long modifyTime) {
		this.modifyTime = modifyTime;
	}

	public String getErrorMsg() {
		if (errorMsg == null) {
			if (lastFireTime != null && nextFireTime != null) {
				long interval = nextFireTime.getTime() - lastFireTime.getTime();
				long nextFireTimeMils;
				if (running) {
					nextFireTimeMils = lastFireTime.getTime() + interval;
				} else {
					nextFireTimeMils = nextFireTime.getTime();
				}
				if (Calendar.getInstance().getTimeInMillis() - nextFireTimeMils > (interval < allowDeviation ? interval : allowDeviation)) {
					errorMsg = "nextFireTime Abnormal";
				} else {
					errorMsg = "";
				}
			}
		}
		return errorMsg;
	}

	public void setErrorMsg(String errorMsg) {
		this.errorMsg = errorMsg;
	}

	public boolean error() {
		return errorMsg != null;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}
}